package com.smartboot.plus.ignite;


import com.smartboot.plus.condition.ConditionGroup;
import com.smartboot.plus.page.IPage;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;


public interface IgniteQueryExecutor<T> {

    IgniteCache<?, ?> getIgniteCache();

    default T selectOne(ConditionGroup condition, Class<T> tClass) {

        String sql = "SELECT * FROM " + getIgniteCache().getName() + " WHERE " + condition;
        SqlFieldsQuery query = new SqlFieldsQuery(sql);
        List<T> result = new ArrayList<>();

        try (QueryCursor<List<?>> cursor = getIgniteCache().query(query)) {
            for (List<?> row : cursor) {
                T t = tClass.newInstance();
                // 获取obj类的字节文件对象
                Field[] fields = tClass.getDeclaredFields();
                for (int i = 0; i < row.size(); i++) {
                    fields[i].setAccessible(true);
                    fields[i].set(t, row.get(i));
                }
                result.add(t);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute selectList query", e);
        }
        if (result == null || result.size() == 0) {
            return null;
        }
        return result.get(0);
    }

    default T selectOne(String condition, Class<T> tClass) {

        String sql = "SELECT * FROM " + getIgniteCache().getName() + " WHERE " + condition;
        SqlFieldsQuery query = new SqlFieldsQuery(sql);
        List<T> result = new ArrayList<>();

        try (QueryCursor<List<?>> cursor = getIgniteCache().query(query)) {
            for (List<?> row : cursor) {
                T t = tClass.newInstance();
                // 获取obj类的字节文件对象
                Field[] fields = tClass.getDeclaredFields();
                for (int i = 0; i < row.size(); i++) {
                    fields[i].setAccessible(true);
                    fields[i].set(t, row.get(i));
                }
                result.add(t);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute selectList query", e);
        }
        if (result == null || result.size() == 0) {
            return null;
        }
        return result.get(0);
    }

    default List<T> selectList(ConditionGroup condition, Class<T> tClass) {

        String sql = "SELECT * FROM " + getIgniteCache().getName() + " WHERE " + condition;
        SqlFieldsQuery query = new SqlFieldsQuery(sql);
        List<T> result = new ArrayList<>();

        try (QueryCursor<List<?>> cursor = getIgniteCache().query(query)) {
            for (List<?> row : cursor) {
                T t = tClass.newInstance();
                // 获取obj类的字节文件对象
                Field[] fields = tClass.getDeclaredFields();
                for (int i = 0; i < row.size(); i++) {
                    fields[i].setAccessible(true);
                    fields[i].set(t, row.get(i));
                }
                result.add(t);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute selectList query", e);
        }
        return result;
    }

    default List<T> selectList(String condition, Class<T> tClass) {

        String sql = "SELECT * FROM " + getIgniteCache().getName() + " WHERE " + condition;
        SqlFieldsQuery query = new SqlFieldsQuery(sql);
        List<T> result = new ArrayList<>();

        try (QueryCursor<List<?>> cursor = getIgniteCache().query(query)) {
            for (List<?> row : cursor) {
                T t = tClass.newInstance();
                // 获取obj类的字节文件对象
                Field[] fields = tClass.getDeclaredFields();
                for (int i = 0; i < row.size(); i++) {
                    fields[i].setAccessible(true);
                    fields[i].set(t, row.get(i));
                }
                result.add(t);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute selectList query", e);
        }
        return result;
    }


    default IPage<T> selectPage(IPage<T> page, ConditionGroup condition, Class<T> tClass) {
        int current = page.getCurrent();
        int size = page.getSize();
        int offset = (current - 1) * size;

        condition.limit(size).offset(offset);

        String sql = "SELECT * FROM " + getIgniteCache().getName() + " WHERE " + condition;

        SqlFieldsQuery query = new SqlFieldsQuery(sql);

        List<T> result = new ArrayList<>();
        try (QueryCursor<List<?>> cursor = getIgniteCache().query(query)) {
            for (List<?> row : cursor) {
                T entity = tClass.getDeclaredConstructor().newInstance();
                Field[] fields = tClass.getDeclaredFields();
                for (int i = 0; i < row.size(); i++) {
                    fields[i].setAccessible(true);
                    fields[i].set(entity, row.get(i));
                }
                result.add(entity);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute selectPage query", e);
        }

        page.setRecords(result);
        //count
        condition.setCount(true);
        String countSql = "SELECT COUNT(*) FROM " + getIgniteCache().getName() + " WHERE " + condition;
        SqlFieldsQuery countQuery = new SqlFieldsQuery(countSql);
        try (QueryCursor<List<?>> cursor = getIgniteCache().query(countQuery)) {
            List<?> row = cursor.getAll().get(0);
            long total = (Long) row.get(0);
            page.setTotal(total);
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute count query", e);
        }

        return page;
    }

    default boolean remove(ConditionGroup condition) {
        String sql = "DELETE FROM " + getIgniteCache().getName() + " WHERE " + condition;

        SqlFieldsQuery query = new SqlFieldsQuery(sql);


        int size = getIgniteCache().query(query).getAll().size();
        return size > 0;
    }

    default boolean removeById(String id) {
        if(id==null){
            return false;
        }
        return ((IgniteCache<String, ?>) getIgniteCache()).remove(id);
    }

}
